package com.ljh.nio.c3;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;


/**
 * @author: Themberfue
 * @date: 2025/5/26 14:35
 * @description:
 */
public class ServerSelector {
    private static final Logger log = LoggerFactory.getLogger(ServerSelector.class);

    public static void main(String[] args) throws IOException {
        // TODO 1. 创建 selector，管理多个 Channel
        Selector selector = Selector.open();

        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);

        // TODO 2. 建立 selector 和 channel 的联系（注册）
        // ! SelectionKey 就是将来建立连接后，可以通过它知道是哪个事件和哪个 channel 的事件
        // ? ops：事件 => accept、connect、read、write
        SelectionKey sscKey = ssc.register(selector, 0, null);
        log.debug("{}", sscKey);

        // TODO 3. 该 key 只关注 accept 事件
        sscKey.interestOps(SelectionKey.OP_ACCEPT);

        ssc.bind(new InetSocketAddress(8080));

        while (true) {
            // TODO 4. select()，没有事件发生，线程阻塞；有事件，线程才会恢复运行
            // ! select 在事件未处理时，不会阻塞，而是接着执行下去。事件要么处理，要么取消，不能置之不理！
            selector.select();

            // TODO 5. 处理事件，selectedKeys 包含了内部的所有事件
            // ! 需要处理的事件（包括之前未处理的，会重新放入）会将由 selector 放进 selectedKeys 里
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                log.debug("{}", key);

                // ? 取消处理该事件
//                key.cancel();

                // TODO 6. 遍历拿到该事件的 channel
                ServerSocketChannel channel = (ServerSocketChannel) key.channel();

                // TODO 7. 接受连接
                // ! 相当于在这里处理了事件 => 接收一个客户端连接。
                SocketChannel sc = channel.accept();
                log.debug("{}", sc);
            }
        }
    }
}
